package Rights;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.management.RuntimeErrorException;

import Public.iRightsAdmission;

public class RightsadmissionService implements iRightsAdmission {
	final private static String usersPath = "\\Users\\Users.txt";
	private static BufferedReader inStream;
	private static FileOutputStream outStream;
	private HashMap<PairUserNameAndPW,UserTicket> userCache;
	private static final ArrayList<Integer> groups = new ArrayList<Integer>();

	private RightsadmissionService() {
	};
	
	private static RightsadmissionService rightsadmissionService;
	
	public static RightsadmissionService getRightsadmissionService() {
		if(rightsadmissionService==null) {
			rightsadmissionService = new RightsadmissionService();
		}
		return rightsadmissionService;
	}

	@Override
	public void addUser(String userName, String password, UserGroup userGroup) {
		editUsers(userName, password, userGroup.getGroup(), Operation.ADD);
	}

	public void delUser(String userName, UserGroup userGroup) {
		editUsers(userName, "", userGroup.getGroup(), Operation.DEL);
	}
	
	public void editUser(String userName, String password, UserGroup userGroup) {
		editUsers(userName, password, userGroup.getGroup(), Operation.EDIT);
	}

	private enum Operation {
		ADD, DEL, EDIT
	}

	private void initializeStreams() throws FileNotFoundException {
		if (inStream != null) {
			inStream = new BufferedReader(new FileReader(usersPath));
		}
		if (outStream != null) {
			outStream = new FileOutputStream(usersPath);
		}
	}
	
	private void updateCache() {
		try {
			initializeStreams();
			initGroups();
			HashMap<PairUserNameAndPW,UserTicket> p_userCache = new HashMap<PairUserNameAndPW,UserTicket>();
			String line;
			String[] parts;
			while((line = inStream.readLine()) != null) {
				parts = line.split(";");
				if(parts.length != 3) {
					throw new RuntimeException();
				}
				Integer group = new Integer(parts[2]);
				if(!isGroup(group)) throw new RuntimeException();
				p_userCache.put(new PairUserNameAndPW(parts[0], parts[1]),new UserTicket(parts[0],new UserGroup(group)));
			}
			this.userCache = p_userCache;
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public UserTicket authenticate(String user,String password) {
		updateCache();
		UserTicket result = null;
		result = this.userCache.get(new PairUserNameAndPW(user, password));
		return result;
	}

	private void initGroups() {
		groups.add(1);
		groups.add(2);
	}
	
	private boolean isGroup(Integer i) {
		if(groups.contains(i)) return true;
		return false;
	}

	private synchronized void editUsers(String userName, String password, int userGroup, Operation operation) {
		updateCache();
		switch (operation) {
		case ADD: {
			if(!userCache.containsKey(userName)) {
				this.userCache.put(new PairUserNameAndPW(userName, password),new UserTicket(userName, new UserGroup(userGroup)));
			}
		}
		case DEL: {
			this.userCache.remove(new PairUserNameAndPW(userName, password));
		}
		case EDIT: {
			this.editUsers(userName, password, 0, Operation.DEL);
			this.editUsers(userName, password, userGroup, Operation.ADD);
		}
		default:
			throw new NoSuchMethodError("Unsopported Operation");
		}
	}

}
